Skip to content
This repository was archived by the owner on May 6, 2019. It is now read-only.

Conversation

stochris
Copy link

This allows the example-app to be used with typescript 2.1.4.

The type inferred for a const variable or readonly property without a type annotation is the type of the initializer as-is.

The type inferred for a let variable, var variable, parameter, or non-readonly property with an initializer and no type annotation is the widened literal type of the initializer.

This means that when not using readonly or const the variable / property will be a string, instead of
a string literal type ( '[Book] Search' )

This does not affect previous versions of typescript

cristian-stoicescu and others added 2 commits December 13, 2016 17:47
    - action types are now instances of anonymous classe
    - action types properties are readonly
    - the type in every action class is readonly
    - the type function now only accepts parameters that extend string
    - the classes have static properties describing the action keys
    - this was done in order to prevent later version of angular-cli complaining the annonymous class wasn't exported
@WrathOfZombies
Copy link

WrathOfZombies commented Dec 20, 2016

Instead of rewriting the actionTypes as classes, why not use the Type Assertion of the type function to achieve the same result?

For example actions/book.ts can be modified to:

export const ActionTypes = {
  SEARCH:           type<'[Book] Search'>('[Book] Search'),
  SEARCH_COMPLETE:  type<'[Book] Search Complete'>('[Book] Search Complete'),
  LOAD:             type<'[Book] Load'>('[Book] Load'),
  SELECT:           type<'[Book] Select'>('[Book] Select')
};

Edit:
Here's the pull request for the same: #91

@stochris
Copy link
Author

stochris commented Dec 21, 2016

Well, writing the same thing twice seems a bit counter intuitive.

@WrathOfZombies
Copy link

Sure, I guess that's about preference. I just wanted to use what's available instead of rewriting to classes. I had to do the same for my project which had a whole bunch of actions.

@Omotayad
Copy link

WrathOfZombies,
I feel your pain. I had to do rewrite the actions by pasting in excel and copying it back to vscode

ADD_ITEM: type('[WFState] ADD_ITEM'), =TRIM(A1) =FIND("'",B1) =FIND("'",B1,C1+2) =MID(B1,C1,(D1-C1) +1) =SUBSTITUTE(B1,"type","type<"&E1&">",1)

Gives ADD_ITEM: type<'[WFState] ADD_ITEM'>('[WFState] ADD_ITEM'),

@MikeRyanDev
Copy link
Member

We will accept TypeScript 2.1 update merge requests after Angular 4 is released. Here is the conversion we want to make to the actions:

Before:

import { Action } from '@ngrx/store';
import { type } from '../util';

export const ActionTypes = {
  OPEN_SIDENAV:   type('[Layout] Open Sidenav'),
  CLOSE_SIDENAV:  type('[Layout] Close Sidenav')
};


export class OpenSidenavAction implements Action {
  type = ActionTypes.OPEN_SIDENAV;
}

export class CloseSidenavAction implements Action {
  type = ActionTypes.CLOSE_SIDENAV;
}


export type Actions
  = OpenSidenavAction
  | CloseSidenavAction;

After:

import { Action } from '@ngrx/store';


export const OPEN_SIDENAV =  '[Layout] Open Sidenav';
export const CLOSE_SIDENAV = '[Layout] Close Sidenav';

export class OpenSidenavAction implements Action {
  readonly type = OPEN_SIDENAV;
}

export class CloseSidenavAction implements Action {
  readonly type = CLOSE_SIDENAV;
}


export type Actions
  = OpenSidenavAction
  | CloseSidenavAction;

Types will flow correctly and it doesn't require the type function to coerce the type of the strings.

@johnhamm
Copy link

Would this still guarantee action type uniqueness though? Isn't that also what the type method guarantees?

@stochris
Copy link
Author

stochris commented Jan 26, 2017 via email

@Matmo10
Copy link

Matmo10 commented Jan 26, 2017

@MikeRyan52 How do the Before/After changes mentioned above affect the usage of the individual ActionTypes in the reducers' switch statements? I haven't kept up with the new Typescript 2.1 features, so I'm still trying to piece together how the types will "flow [more] correctly". I guess I can wait for the real PR to see it in action...just eager to play with all the new tech 😄

@karptonite
Copy link

@MikeRyan52 correct me if I'm wrong, but it looks to me as if we could immediately start using the new action definition style #88 (comment) if we are using typescript 2.1. Is that correct? It seems to work for me, but I may be missing some cases.

@rkrisztian
Copy link

rkrisztian commented Feb 9, 2017

(I've rewritten this comment because I was wrong yesterday.)

The following works:

namespace Types {
	export const LOAD_HEROES = '[Heroes] Load Heroes';
	export const LOAD_HEROES_SUCCESS = '[Heroes] Load Heroes Success';
}

class LoadHeroes implements Action {
	readonly type = Types.LOAD_HEROES;
}

class LoadHeroesSuccess implements Action {
	readonly type = Types.LOAD_HEROES_SUCCESS;
	constructor(public payload: Hero[]) {}
}

type All = LoadHeroes | LoadHeroesSuccess;

The key is in the readonly and const keywords. Creating classes for grouping constants is rather an overkill in my opinion, but it works too if you prefer (and the lines look somewhat shorter that way):

const Types = new class {
	readonly LOAD_HEROES = '[Heroes] Load';
	readonly LOAD_HEROES_SUCCESS = '[Heroes] Load Success';
}

@rkrisztian
Copy link

rkrisztian commented Feb 10, 2017

Now that we don't need to use type anymore, I was thinking of doing some neat things like:

export namespace Types {
	const prefix = '[Heroes]';

	export const LOAD_HEROES = `${prefix} Load Heroes`;
	export const LOAD_HEROES_SUCCESS = `${prefix} Load Heroes Success`;
}

But it does not work. Not even in this form:

export namespace Types {
	const prefix = '[Heroes] ';

	export const LOAD_HEROES = prefix + 'Load Heroes';
	export const LOAD_HEROES_SUCCESS = prefix + 'Load Heroes Success';
}

And ng serve does not always report the problem. :(

@dereklin
Copy link

@MikeRyan52 The after code

import { Action } from '@ngrx/store';


export const OPEN_SIDENAV =  '[Layout] Open Sidenav';
export const CLOSE_SIDENAV = '[Layout] Close Sidenav';

export class OpenSidenavAction implements Action {
  readonly type = OPEN_SIDENAV;
}

export class CloseSidenavAction implements Action {
  readonly type = CLOSE_SIDENAV;
}


export type Actions
  = OpenSidenavAction
  | CloseSidenavAction;

doesn't work for actions with actions having payload and having no payload mixed together. And it doesn't work with different payload types:

export class LoadAction implements Action {
  public readonly type = LOAD;
  constructor(public payload: Ticker) { }
}

export class UpdateAction implements Action {
  public readonly type = UPDATE;
  constructor(public payload: any[]) { }
}

export class StopUpdateAction implements Action {
  public readonly type = STOP_UPDATE;
}

export type Actions
  = StopUpdateAction |
    LoadAction |
    UpdateAction;

In my reducer, it complains that the 'payload' does not exist on type 'Actions'. And even when they all have payload, if the types are different; for example in my case, it will complain slice doesn't exist in any[] | Ticker (when I want to use .slice on my array payload)

@bypotatoes
Copy link
Contributor

I've just realized the main goal of type function was coercing the type of the strings not having uniqueness. Could someone help to catch an idea of having type property with literal type vs string constant, for now, I can't find any profit? Thanks

@krjordan
Copy link
Collaborator

Typescript was upgraded to 2.2 via #143

@krjordan krjordan closed this Apr 12, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.